import type { Plugin } from "vite"
import { join, parse, relative } from "path"
import { existsSync, readdirSync, statSync, writeFileSync } from "fs"
import chokidar from "chokidar"

interface Options {
  imageDir?: string
  outputFile?: string
  formats?: string[]
}

export default function imgIndexPlugin(options: Options = {}): Plugin {
  const {
    imageDir = join(process.cwd(), "src/assets/images"),
    outputFile = join(process.cwd(), "src/assets/images/index.ts"),
    formats = [".png", ".jpg", ".jpeg", ".gif", ".svg"],
  } = options

  let isBuild = false

  // 生成首字母大写的合法变量名 (PascalCase)
  const formatVarName = (filename: string) => {
    return filename
      .replace(/[^a-zA-Z0-9_]/g, "_") // 非法字符转下划线
      .replace(/(?:^|_)(\w)/g, (_, char) => char.toUpperCase()) // 首字母及分隔符后字母大写 [6]()
      .replace(/^(\d)/, "_$1") // 数字开头加下划线
  }

  // 生成文件内容
  const generateContent = (dir: string) => {
    let imports: string[] = []
    let exports: string[] = ["// Auto-generated by vite-plugin-img-index\n"]

    const walk = (currentDir: string) => {
      const files = readdirSync(currentDir)

      files.forEach((file) => {
        const fullPath = join(currentDir, file)
        if (statSync(fullPath).isDirectory()) {
          walk(fullPath)
        } else if (formats.includes(parse(file).ext.toLowerCase())) {
          const relativePath = relative(imageDir, fullPath)
          const varName = formatVarName(parse(file).name) // 使用新格式化函数
          imports.push(`import  ${varName} from './${relativePath}'`)
          exports.push(`   ${varName},`)
        }
      })
    }

    walk(dir)

    return [...imports, `\nexport const assetsImgs = {`, ...exports, "}"].join("\n")
  }

  // 写入文件
  const generateIndexFile = () => {
    if (!existsSync(imageDir)) return

    const content = generateContent(imageDir)
    writeFileSync(outputFile, content)
    console.log(
      `[img-index]  Index file updated at ${new Date().toLocaleTimeString()}`
    )
  }

  return {
    name: "vite-plugin-img-index",

    configResolved(config) {
      isBuild = config.command === "build"
    },

    buildStart() {
      if (isBuild) {
        generateIndexFile()
      } else {
        const watcher = chokidar.watch(imageDir, {
          ignoreInitial: true,
          persistent: true,
        })

        watcher
          .on("add", generateIndexFile)
          .on("unlink", generateIndexFile)
          .on("ready", generateIndexFile)
      }
    },
  }
}
